package com.jap.service;

import com.jap.dao.UserRepository;
import com.jap.entity.User;
import com.jap.entity.UserDetails;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 *
 * 添加事务注解在一个事务中调用懒加载不会报  no session 异常
 * @Description
 * @Author 顾志杰
 * @Date 2022/9/12 10:46
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class UserService {

  /**
   * 将 Page<T> 转换为 Page<R>，并使用 BeanUtils.copyProperties 进行属性复制。
   *
   * @param <T> 源实体类型
   * @param <R> 目标视图类型
   * @param page 源 Page 对象
   * @param targetClass 目标视图类的 Class 对象
   * @return 转换后的 Page<R>
   */
  protected static <T, R> Page<R> convertPage(Page<T> page, Class<R> targetClass){
    try {
      List<T> content = page.getContent();
      List<R> convertedContent = new ArrayList<>(content.size());
      for (T item : content) {
        R targetObject = targetClass.getDeclaredConstructor().newInstance();
        BeanUtils.copyProperties(item, targetObject);
        convertedContent.add(targetObject);
      }
      return new PageImpl<>(convertedContent, page.getPageable(), page.getTotalElements());
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  @Autowired
  private UserRepository userRepository;

  public void insert() {
    User user = new User();
    user.setUserName("test");
    user.setPassWord("password");
    UserDetails userDetails = new UserDetails();
    userDetails.setName("姓名");
    userDetails.setTel("13222222222");
    user.setUserDetails(userDetails);
    userRepository.saveAndFlush(user);
  }

  public Page<User> users(Pageable pageable) {
    //排序
    Sort sort =new Sort(Sort.Direction.ASC,"age");
    PageRequest pageRequest = PageRequest.of(1,2,sort);

    Page<User> page = userRepository.findAll((Specification<User>) (root, query, criteriaBuilder) -> {
      List<Predicate> list = new ArrayList<>();
      //去重
      query.multiselect(root.get("id")).distinct(true);


      //in
      CriteriaBuilder.In<Object> in = criteriaBuilder.in(root.get("userDetails").get("id"));
      List<String> type = Arrays.asList("1", "2");
      type.forEach(in::value);
      list.add(in);

      //等于
      list.add(criteriaBuilder.equal(root.get("userName").as(String.class), ""));

      //like
      list.add(criteriaBuilder.like(root.get("userDetails").get("name").as(String.class), "%name%"));

      //大于
      list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.now()));

      //小于
      list.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.now()));

      //区间
      list.add(criteriaBuilder.between(root.get("createTime").as(LocalDateTime.class), LocalDateTime.now(),LocalDateTime.now()));

      //组合查询 and
      Predicate and01 = criteriaBuilder.ge(root.get("age").as(Integer.class), 20);
      Predicate adn02 = criteriaBuilder.equal(root.get("name").as(String.class),"赵云");
      list.add(criteriaBuilder.and(and01, adn02)) ;

      //组合查询 or
      Predicate or01 = criteriaBuilder.ge(root.get("age").as(Integer.class), 20);
      Predicate or02 = criteriaBuilder.equal(root.get("name").as(String.class),"赵云");
      list.add(criteriaBuilder.and(or01, or02)) ;


      //排序
      query.orderBy(criteriaBuilder.desc(root.get("createTime").as(LocalDateTime.class)));
      Predicate[] p = new Predicate[list.size()];
      return criteriaBuilder.and(list.toArray(p));
    }, pageRequest);
    return page;
  }
}
